package com.gitee.xiao.check;

/**
 * @author wang xiao
 * date 2024/7/10
 */
public class FaceRecognitionService {

    private frontal_face_detector detector;
    private shape_predictor sp;
    private anet_type net;
    private List<FaceProfile> knownFaces;

    public FaceRecognitionService() {
        detector = dlib.get_frontal_face_detector();
        sp = new shape_predictor("shape_predictor_68_face_landmarks.dat");
        net = new anet_type();
        dlib.deserialize("dlib_face_recognition_resnet_model_v1.dat").to(net);

        knownFaces = loadKnownFaces();
    }

    // 加载已知人脸数据
    private List<FaceProfile> loadKnownFaces() {
        List<FaceProfile> faces = new ArrayList<>();
        // 读取已知人脸图像和特征
        // 这里可以从数据库或文件系统加载已知人脸数据
        return faces;
    }

    // 识别人脸
    public String recognize(String imageBase64) {
        // 解码Base64图片
        byte[] decodedBytes = Base64.getDecoder().decode(imageBase64);
        Mat img = ImgCodecs.imdecode(new Mat(decodedBytes), ImgCodecs.IMREAD_COLOR);

        // 检测人脸
        dlib.rectangles faces = detector.apply(img);
        ArrayList<Matrix> faceDescriptors = new ArrayList<>();
        for (rect face : faces) {
            full_object_detection shape = sp.apply(img, face);
            Matrix face_chip = new Matrix();
            extract_image_chip.apply(img, get_face_chip_details.apply(shape, 150, 0.25) , face_chip);
            faceDescriptors.add(net.apply(face_chip));
        }

        // 比对人脸
        if (faceDescriptors.size() > 0) {
            Matrix faceDescriptor = faceDescriptors.get(0);
            String recognizedPerson = findBestMatch(faceDescriptor);
            return recognizedPerson;
        }

        return "Unknown";
    }

    // 比对人脸特征，找到最佳匹配
    private String findBestMatch(Matrix faceDescriptor) {
        double minDistance = Double.MAX_VALUE;
        String bestMatch = "Unknown";

        for (FaceProfile knownFace : knownFaces) {
            double distance = length(subtract(faceDescriptor, knownFace.getFaceDescriptor()));
            if (distance < minDistance) {
                minDistance = distance;
                bestMatch = knownFace.getName();
            }
        }

        return bestMatch;
    }
}
